package com.lq.learningTest.encapsulation;

/**
 * 超级链表带头节点，第一个节点为头节点next指针所指
 */
public class SuperLink {

    // 链表的长度
    private int size;
    // 维护头节点
    private Node first;
    // 维护尾节点
    private Node last;

    //判断函数是否成功执行的标准
    private boolean flag = false;

    // 无参构造器
    public SuperLink(){
        first = new Node();
        last = new Node();
    }

    /**
     * 带头结点链表的尾插法，添加元素至链表尾部
     * @param data
     */
    public boolean add(Integer data){
        Node node = new Node(data,null);
        //如果链表为空链表，那么添加的节点直接为第一个节点,否则就让尾节点指向新的节点
        if (first.getNext() == null){
            first.setNext(node);
        } else {
            last.setNext(node);
        }
        //把尾指针指向新的节点
        last = node;
        size++;
        flag = true;
        if (flag){
            flag = false;
            return true;
        }else return false;
    }

    /**
     * 在指定下标添加元素
     * @param index
     * @param data
     * @return
     */
    public boolean add(int index,Integer data){
        Node node = getNode(-- index);
        Node newNode = new Node(data,null);

        //往链表中间插入节点，列如把新建结点插入到第二个结点上，就需要先把新结点的next指向第一个结点的Next
        //再把第一个结点的next指向新结点
        newNode.setNext(node.getNext());
        node.setNext(newNode);
        size++;
        flag = true;
        if (flag) {
            flag = false;
            return true;
        }return false;
    }

    //

    /**
     * 删除节点,从首结点开始
     * @return
     */
    public boolean remove(){
        if (size <= 0){
            return false;
        }else if (size == 1){
            first.setNext(null);
            size --;
        }else{
            first.setNext(first.getNext().getNext());
            size--;
        }
        flag = true;
        if (flag) {
            flag = false;
            return true;
        }else return false;
    }

    /**
     * 删除指定元素
     * @param index
     * @return
     */
    public Integer remove(int index){
        if (size < 0){
            return null;
        }
        if(size == 1){
            first.setNext(null);
            last = null;
        } else {
            //要删除的下标节点的前一个节点直接指向下标节点的下一个节点,这里牵扯到两个连续的结点，所以如果size==1的话要单独判断
            Node node = getNode(-- index);
            node.setNext(node.getNext().getNext());
        }
        size--;
        flag = true;
        if (flag) {
            flag = false;
            return getNode(index).getData();
        }return null;
    }

    /**
     * 修改指定下标的元素
     * @param index
     * @param data
     * @return
     */
    public boolean set(int index,Integer data){
        // 找到第index个
        Node node = getNode(index);
        node.setData(data);
        flag = true;
        if (flag) {
            flag = false;
            return true;
        }else return false;
    }

    /**
     * 获取指定下标的元素
     * @param index
     * @return
     */
    public Integer get(int index){
        Integer data = getNode(index).getData();
        if (data != null) {
            return getNode(index).getData();
        }else return null;
    }

    /**
     * 查看当前有多少个结点
     * @return
     */
    public int size(){
        return size;
    }

    /**
     * 带结点的单链表，输入下标返回下标对应节点的地址
     * @param index
     * @return
     */
    private Node getNode(int index){
        // 边界判断
        if(index < 0){
            index = 0;
        }
        if(index >= size){
            index = size;
        }
        // 带头节点的链表了，first的结点getNext()得到第一个带值的结点地址。从第一个节点一直getNext()直到找到第index个
        //这里开始游标cursor是在头结点上
        Node cursor = first;
        if (index == 0) {
            return cursor;
        } else{
            for (int i = 0; i < index; i++) {
                cursor = cursor.getNext();
            }
        }
        return cursor;
    }
}



